home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
H_FOLDER
/
RT.H
< prev
next >
Wrap
Text File
|
1990-03-02
|
32KB
|
1,098 lines
/*
* Definitions and declarations used throughout the run-time system.
* These are also used by the linker in constructing data for use by
* the run-time system.
*/
#ifdef StandardC
#include <time.h>
#endif /* StandardC */
#include "::h:cpuconf.h"
#include "::h:memsize.h"
/*
* Constants that are not likely to vary between implementations.
*/
#define BitOffMask (IntBits-1)
#define CsetSize (256/IntBits) /* number of ints to hold 256 cset
* bits. Use (256/IntBits)+1 if
* 256 % IntBits != 0 */
#define MinListSlots 8 /* number of elements in an expansion
* list element block */
#define MaxCvtLen 257 /* largest string in conversions; the extra
* one is for a terminating null */
#define MaxReadStr 512 /* largest string to read() in one piece */
#define MaxIn 32767 /* largest number of bytes to read() at once */
#define RandA 1103515245 /* random seed multiplier */
#define RandC 453816694 /* random seed additive constant */
#define RanScale 4.65661286e-10 /* random scale factor = 1/(2^31-1)) */
/*
* File status flags in status field of file blocks.
*/
#define Fs_Read 01 /* read access */
#define Fs_Write 02 /* write access */
#define Fs_Create 04 /* file created on open */
#define Fs_Append 010 /* append mode */
#define Fs_Pipe 020 /* reading/writing on a pipe */
/*
* Definitions for interpreter actions.
*/
#define A_Failure 1 /* routine failed */
#define A_Suspension 2 /* routine suspended */
#define A_Return 3 /* routine returned */
#define A_Pret_uw 4 /* interp unwind for Op_Pret */
#define A_Unmark_uw 5 /* interp unwind for Op_Unmark */
#define A_Resumption 6 /* resume generator */
#define A_Pfail_uw 7 /* interp unwind for Op_Pfail */
#define A_Lsusp_uw 8 /* interp unwind for Op_Lsusp */
#define A_Eret_uw 9 /* interp unwind for Op_Eret */
#define A_Coact 10 /* co-expression activated */
#define A_Coret 11 /* co-expression returned */
#define A_Cofail 12 /* co-expression failed */
/*
* Codes returned by invoke to indicate action.
*/
#define I_Builtin 201 /* A built-in routine is to be invoked */
#define I_Fail 202 /* goal-directed evaluation failed */
#define I_Continue 203 /* Continue execution in the interp loop */
#define I_Vararg 204 /* A function with a variable number of args */
/*
* Codes returned by runtime support routines.
* Note, some conversion routines also return type codes. Other routines may
* return positive values other than return codes. sort() places restrictions
* on Less, Equal, and Greater.
*/
#define Less -1
#define Equal 0
#define Greater 1
#define CvtFail -2
#define Cvt -3
#define NoCvt -4
#define Failure -5
#define Defaulted -6
#define Success -7
#define Error -8
/*
* Generator types.
*/
#define G_Csusp 1
#define G_Esusp 2
#define G_Psusp 3
/*
* Type codes (descriptors and blocks).
*/
#define T_Null 0 /* null value */
#define T_Integer 1 /* integer */
#ifdef LargeInts
#define T_Bignum 2 /* long integer */
#endif /* LargeInts */
#define T_Real 3 /* real number */
#define T_Cset 4 /* cset */
#define T_File 5 /* file */
#define T_Proc 6 /* procedure */
#define T_List 7 /* list header */
#define T_Table 8 /* table header */
#define T_Record 9 /* record */
#define T_Telem 10 /* table element */
#define T_Lelem 11 /* list element */
#define T_Tvsubs 12 /* substring trapped variable */
#define T_Tvkywd 13 /* keyword trapped variable */
#define T_Tvtbl 14 /* table element trapped variable */
#define T_Set 15 /* set header */
#define T_Selem 16 /* set element */
#define T_Refresh 17 /* refresh block */
#define T_Coexpr 18 /* co-expression */
#define T_External 19 /* external block */
#define T_Slots 20 /* set/table hash slots */
#define MaxType 20 /* maximum type number */
/*
* Descriptor types and flags.
*/
#define D_Null (word)(T_Null | F_Nqual)
#define D_Integer (word)(T_Integer | F_Nqual)
#ifdef LargeInts
#define D_Bignum (word)(T_Bignum | F_Ptr | F_Nqual)
#endif /* LargeInts */
#define D_Real (word)(T_Real | F_Ptr | F_Nqual)
#define D_Cset (word)(T_Cset | F_Ptr | F_Nqual)
#define D_File (word)(T_File | F_Ptr | F_Nqual)
#define D_Proc (word)(T_Proc | F_Ptr | F_Nqual)
#define D_List (word)(T_List | F_Ptr | F_Nqual)
#define D_Table (word)(T_Table | F_Ptr | F_Nqual)
#define D_Telem (word)(T_Telem | F_Ptr | F_Nqual)
#define D_Tvsubs (word)(T_Tvsubs | D_Tvar)
#define D_Tvkywd (word)(T_Tvkywd | D_Tvar)
#define D_Tvtbl (word)(T_Tvtbl | D_Tvar)
#define D_Record (word)(T_Record | F_Ptr | F_Nqual)
#define D_Set (word)(T_Set | F_Ptr | F_Nqual)
#define D_Refresh (word)(T_Refresh | F_Ptr | F_Nqual)
#define D_Coexpr (word)(T_Coexpr | F_Ptr | F_Nqual)
#define D_External (word)(T_External | F_Ptr | F_Nqual)
#define D_Slots (word)(T_Slots | F_Ptr | F_Nqual)
#define D_Var (word)(F_Var | F_Nqual | F_Ptr)
#define D_Tvar (word)(D_Var | F_Tvar)
#define TypeMask 63 /* type mask */
#define OffsetMask (~(D_Tvar)) /* offset mask for variables */
/*
* Run-time data structures.
*/
/*
* Icode consists of operators and arguments. Operators are small integers,
* while arguments may be pointers. To conserve space in icode files on
* computers with 16-bit ints, icode is written by the linker as a mixture
* of ints and words (longs). When an icode file is read in and processed
* by the interpreter, it looks like a C array of mixed ints and words.
* Accessing this "nonstandard" structure is handled by a union of int and
* word pointers and incrementing is done by incrementing the appropriate
* member of the union (see the interpreter). This is a rather dubious
* method and certainly not portable. A better way might be to address
* icode with a char *, but the incrementing code might be inefficient
* (at a place that experiences a lot of execution activity).
*
* For the moment, the dubious coding is isolated under control of the
* size of integers.
*/
#if IntBits == 16
typedef union {
int *op;
word *opnd;
} inst;
#else /* IntBits == 16 */
typedef union {
word *op;
word *opnd;
} inst;
#endif /* IntBits == 16 */
/*
* Descriptor
*/
struct descrip { /* descriptor */
word dword; /* type field */
union {
word integr; /* integer value */
char *sptr; /* pointer to character string */
union block *bptr; /* pointer to a block */
dptr descptr; /* pointer to a descriptor */
} vword;
};
struct sdescrip {
word length; /* length of string */
char *string; /* pointer to string */
};
/*
* Run-time error numbers and text.
*/
struct errtab {
int err_no; /* error number */
char *errmsg; /* error message */
};
/*
* Frame markers
*/
struct ef_marker { /* expression frame marker */
inst ef_failure; /* failure ipc */
struct ef_marker *ef_efp; /* efp */
struct gf_marker *ef_gfp; /* gfp */
word ef_ilevel; /* ilevel */
};
struct pf_marker { /* procedure frame marker */
word pf_nargs; /* number of arguments */
struct pf_marker *pf_pfp; /* saved pfp */
struct ef_marker *pf_efp; /* saved efp */
struct gf_marker *pf_gfp; /* saved gfp */
dptr pf_argp; /* saved argp */
inst pf_ipc; /* saved ipc */
word pf_ilevel; /* saved ilevel */
dptr pf_scan; /* saved scanning environment */
struct descrip pf_locals[1]; /* descriptors for locals */
};
struct gf_marker { /* generator frame marker */
word gf_gentype; /* type */
struct ef_marker *gf_efp; /* efp */
struct gf_marker *gf_gfp; /* gfp */
inst gf_ipc; /* ipc */
struct pf_marker *gf_pfp; /* pfp */
dptr gf_argp; /* argp */
};
/*
* Generator frame marker dummy -- used only for sizing "small"
* generator frames where procedure infomation need not be saved.
* The first five members here *must* be identical to those for
* gf_marker.
*/
struct gf_smallmarker { /* generator frame marker */
word gf_gentype; /* type */
struct ef_marker *gf_efp; /* efp */
struct gf_marker *gf_gfp; /* gfp */
inst gf_ipc; /* ipc */
};
#ifdef LargeInts
typedef unsigned int DIGIT;
struct b_bignum { /* large integer block */
word title; /* T_Bignum */
word blksize; /* block size */
word msd, lsd; /* most and least significant digits */
int sign; /* sign; 0 positive, 1 negative */
DIGIT digits[1]; /* digits */
};
#endif /* LargeInts */
struct b_real { /* real block */
word title; /* T_Real */
double realval; /* value */
};
struct b_cset { /* cset block */
word title; /* T_Cset */
word size; /* size of cset */
int bits[CsetSize]; /* array of bits */
};
struct b_file { /* file block */
word title; /* T_File */
FILE *fd; /* Unix file descriptor */
word status; /* file status */
struct descrip fname; /* file name (string qualifier) */
};
struct b_proc { /* procedure block */
word title; /* T_Proc */
word blksize; /* size of block */
union { /* entry points for */
int (*ccode)(); /* C routines */
uword ioff; /* and icode as offset */
pointer icode; /* and icode as absolute pointer */
} entryp;
word nparam; /* number of parameters */
word ndynam; /* number of dynamic locals */
word nstatic; /* number of static locals */
word fstatic; /* index (in global table) of first static */
struct descrip pname; /* procedure name (string qualifier) */
struct descrip lnames[1]; /* list of local names (qualifiers) */
};
/*
* b_iproc blocks are used to statically initialize information about
* functions. They are identical to b_proc blocks except for
* the pname field which is a sdecrip (simple/string descriptor) instead
* of a descrip. This is done because unions cannot be initialized.
*/
struct b_iproc { /* procedure block */
word ip_title; /* T_Proc */
word ip_blksize; /* size of block */
int (*ip_entryp)(); /* entry point (code) */
word ip_nparam; /* number of parameters */
word ip_ndynam; /* number of dynamic locals */
word ip_nstatic; /* number of static locals */
word ip_fstatic; /* index (in global table) of first static */
struct sdescrip ip_pname; /* procedure name (string qualifier) */
struct descrip ip_lnames[1]; /* list of local names (qualifiers) */
};
struct b_list { /* list-header block */
word title; /* T_List */
word size; /* current list size */
word id; /* identification number */
union block *listhead; /* pointer to first list-element block */
union block *listtail; /* pointer to last list-element block */
};
struct b_lelem { /* list-element block */
word title; /* T_Lelem */
word blksize; /* size of block */
union block *listprev; /* previous list-element block */
union block *listnext; /* next list-element block */
word nslots; /* total number of slots */
word first; /* index of first used slot */
word nused; /* number of used slots */
struct descrip lslots[1]; /* array of slots */
};
struct b_slots { /* set/table hash slots */
word title; /* T_Slots */
word blksize; /* size of block */
union block *hslots[HSlots]; /* array of slots (HSlots * 2^n entries) */
};
struct b_table { /* table-header block */
word title; /* T_Table */
word size; /* current table size */
word id; /* identification number */
word mask; /* mask to get slot num, equals n slots - 1 */
struct b_slots *hdir[HSegs]; /* directory of hash slot segments */
struct descrip defvalue; /* default table element value */
};
struct b_telem { /* table-element block */
word title; /* T_Telem */
union block *clink; /* hash chain link */
uword hashnum; /* for ordering chain */
struct descrip tref; /* entry value */
struct descrip tval; /* assigned value */
};
/*
* A set header must be a proper prefix of a table header,
* and a set element must be a proper prefix of a table element.
*/
struct b_set { /* set-header block */
word title; /* T_Set */
word size; /* size of the set */
word id; /* identification number */
word mask; /* mask to get slot num, equals n slots - 1 */
struct b_slots *hdir[HSegs]; /* directory of hash slot segments */
};
struct b_selem { /* set-element block */
word title; /* T_Selem */
union block *clink; /* hash chain link */
uword hashnum; /* hash number */
struct descrip setmem; /* the element */
};
struct b_record { /* record block */
word title; /* T_Record */
word blksize; /* size of block */
word id; /* identification number */
union block *recdesc; /* pointer to record constructor */
struct descrip fields[1]; /* fields */
};
/*
* Alternate uses for procedure block fields, applied to records.
*/
#define nfields nparam /* number of fields */
#define recnum nstatic /* record number */
#define recid fstatic /* record serial number */
#define recname pname /* record name */
struct b_tvkywd { /* keyword trapped variable block */
word title; /* T_Tvkywd */
int (*putval)(); /* assignment function for keyword */
struct descrip kyval; /* keyword value */
struct descrip kyname; /* keyword name */
};
struct b_tvsubs { /* substring trapped variable block */
word title; /* T_Tvsubs */
word sslen; /* length of substring */
word sspos; /* position of substring */
struct descrip ssvar; /* variable that substring is from */
};
struct b_tvtbl { /* table element trapped variable block */
word title; /* T_Tvtbl */
union block *clink; /* pointer to table header block */
uword hashnum; /* hash number */
struct descrip tref; /* entry value */
struct descrip tval; /* reserved for assigned value */
};
struct b_coexpr { /* co-expression stack block */
word title; /* T_Coexpr */
word size; /* number of results produced */
word id; /* identification number */
struct b_coexpr *nextstk; /* pointer to next allocated stack */
struct pf_marker *es_pfp; /* current pfp */
struct ef_marker *es_efp; /* efp */
struct gf_marker *es_gfp; /* gfp */
dptr es_argp; /* argp */
inst es_ipc; /* ipc */
word es_ilevel; /* interpreter level */
word *es_sp; /* sp */
dptr tvalloc; /* where to place transmitted value */
struct descrip freshblk; /* refresh block pointer */
struct astkblk *es_actstk; /* pointer to activation stack structure */
word cstate[CStateSize]; /* C state information */
};
struct astkblk { /* co-expression activator-stack block */
int nactivators; /* number of valid activator entries in
* this block */
struct astkblk *astk_nxt; /* next activator block */
struct actrec { /* activator record */
word acount; /* number of calls by this activator */
struct b_coexpr *activator; /* the activator itself */
} arec[ActStkBlkEnts];
};
struct b_refresh { /* co-expression block */
word title; /* T_Refresh */
word blksize; /* size of block */
word *ep; /* entry point */
word numlocals; /* number of locals */
struct pf_marker pfmkr; /* marker for enclosing procedure */
struct descrip elems[1]; /* arguments and locals, including Arg0 */
};
struct b_external { /* external block */
word title; /* T_External */
word blksize; /* size of block */
word descoff; /* offset to first descriptor */
word exdata[1]; /* words of external data */
};
union block { /* general block */
#ifdef LargeInts
struct b_bignum bignumblk;
#endif /* LargeInts */
struct b_real realblk;
struct b_cset cset;
struct b_file file;
struct b_proc proc;
struct b_list list;
struct b_lelem lelem;
struct b_table table;
struct b_telem telem;
struct b_set set;
struct b_selem selem;
struct b_record record;
struct b_tvkywd tvkywd;
struct b_tvsubs tvsubs;
struct b_tvtbl tvtbl;
struct b_refresh refresh;
struct b_coexpr coexpr;
struct b_external externl;
struct b_slots slots;
};
/*
* Declarations for entries in tables associating icode location with
* source program location.
*/
struct ipc_fname {
word ipc; /* offset of instruction into code region */
word fname; /* offset of file name into string region */
};
struct ipc_line {
word ipc; /* offset of instruction into code region */
int line; /* line number */
};
/*
* External declarations.
*/
extern char *code; /* start of icode */
extern word stksize; /* size of co-expression stacks in words */
extern word *stackend; /* end of evaluation stack */
extern struct b_coexpr *stklist;/* base of co-expression stack list */
extern word mstksize; /* size of main stack in words */
extern char *statbase; /* start of static space */
extern char *statend; /* end of static space */
extern char *statfree; /* static space free list header */
extern word statsize; /* size of static space */
extern word statincr; /* size of increment for static space */
extern word ssize; /* size of string space (bytes) */
extern char *strbase; /* start of string space */
extern char *strend; /* end of string space */
extern char *strfree; /* string space free pointer */
extern word abrsize; /* size of allocated block region (words) */
extern char *blkbase; /* base of allocated block region */
extern char *blkend; /* maximum address in allocated block region */
extern char *blkfree; /* first free location in allocated block region */
extern int bsizes[]; /* sizes of blocks */
extern int firstd[]; /* offset (words) of first descrip. */
extern char *blkname[]; /* print names for block types. */
extern uword segsize[]; /* size of hash bucket segment */
extern struct b_tvkywd tvky_err; /* trapped variable for &error */
extern struct b_tvkywd tvky_pos; /* trapped variable for &pos */
extern struct b_tvkywd tvky_ran; /* trapped variable for &random */
extern struct b_tvkywd tvky_sub; /* trapped variable for &subject */
extern struct b_tvkywd tvky_trc; /* trapped variable for &trace */
#define k_error tvky_err.kyval.vword.integr /* value of &error */
#define k_pos tvky_pos.kyval.vword.integr /* value of &pos */
#define k_random tvky_ran.kyval.vword.integr /* value of &random */
#define k_subject tvky_sub.kyval /* value of &subject */
#define k_trace tvky_trc.kyval.vword.integr /* value of &trace */
extern struct b_cset k_ascii; /* value of &ascii */
extern struct b_cset k_cset; /* value of &cset */
extern struct b_cset k_digits; /* value of &lcase */
extern struct b_file k_errout; /* value of &errout */
extern struct b_file k_input; /* value of &input */
extern struct b_cset k_lcase; /* value of &lcase */
extern struct b_cset k_letters; /* value of &letters */
extern int k_level; /* value of &level */
extern char *k_errortext; /* value of &errortext */
extern int k_errornumber; /* value of &errornumber */
extern struct descrip k_errorvalue; /* value of &errorvalue */
extern struct descrip k_main; /* value of &main */
extern struct descrip k_current; /* ¤t */
extern struct b_file k_output; /* value of &output */
extern struct b_cset k_ucase; /* value of &ucase */
#ifdef SASC
extern clock_t starttime; /* start time in milliseconds */
#else /* SASC */
extern long starttime; /* start time in milliseconds */
#endif /* SASC */
extern struct descrip nulldesc; /* null value */
extern struct descrip zerodesc; /* zero */
extern struct descrip onedesc; /* one */
extern struct descrip emptystr; /* empty string */
extern struct descrip blank; /* blank */
extern struct descrip letr; /* letter "r" */
extern struct descrip maps2; /* second argument to map() */
extern struct descrip maps3; /* third argument to map() */
extern struct descrip input; /* &input */
extern struct descrip errout; /* &errout */
extern struct descrip lcase; /* lowercase string */
extern struct descrip ucase; /* uppercase string */
extern int ntended; /* number of active tended descriptors */
extern struct descrip tended[]; /* tended descriptors */
extern word *sp; /* interpreter stack pointer */
extern word *stack; /* interpreter stack base */
extern struct pf_marker *pfp; /* procedure frame pointer */
extern struct ef_marker *efp; /* expression frame pointer */
extern struct gf_marker *gfp; /* generator frame pointer */
extern inst ipc; /* interpreter program counter */
extern dptr argp; /* argument pointer */
extern int ilevel; /* interpreter level */
#ifdef ExecImages
extern int dumped; /* the interpreter has been dumped */
#endif /* ExecImages */
#if EBCDIC == 2
extern char ToEBCDIC[], FromEBCDIC[]; /* ASCII<->EBCDIC maps */
#define ToAscii(e) (FromEBCDIC[e])
#define FromAscii(e) (ToEBCDIC[e])
#else /* EBCDIC == 2 */
#define ToAscii(e) (e)
#define FromAscii(e) (e)
#endif /* EBCDIC == 2 */
/*
* Evaluation stack overflow margin
*/
#define PerilDelta 100
/*
* Macro definitions related to descriptors.
*/
/*
* The following code is operating-system dependent [@rt.01]. Define
* PushAval for computers that store longs and pointers differently.
*/
#if PORT
#define PushAVal(x) PushVal(x)
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS
#define PushAVal(x) PushVal(x)
#endif /* AMIGA || ATARI_ST || HIGHC_386 ... */
#if MSDOS || OS2
static union {
pointer stkadr;
word stkint;
} stkword;
#define PushAVal(x) {sp++; \
stkword.stkadr = (char *)(x); \
*sp = stkword.stkint;}
#endif /* MSDOS || OS2 */
/*
* End of operating-system specific code.
*/
/*
* Pointer to block.
*/
#define BlkLoc(d) ((d).vword.bptr)
/*
* Check for null-valued descriptor.
*/
#define ChkNull(d) ((d).dword==D_Null)
/*
* Dereference descriptor.
*/
#define DeRef(d) (Var(d) ? deref(&d) : Success)
/*
* Check for equivalent descriptors.
*/
#define EqlDesc(d1,d2) ((d1).dword == (d2).dword && BlkLoc(d1) == BlkLoc(d2))
/*
* Integer value.
*/
#define IntVal(d) ((d).vword.integr)
/*
* Offset from top of block to value of variable.
*/
#define Offset(d) ((d).dword & OffsetMask)
/*
* Check for pointer.
*/
#define Pointer(d) ((d).dword & F_Ptr)
/*
* Check for qualifier.
*/
#define Qual(d) (!((d).dword & F_Nqual))
/*
* Length of string.
*/
#define StrLen(q) ((q).dword)
/*
* Location of first character of string.
*/
#define StrLoc(q) ((q).vword.sptr)
/*
* Check for trapped variable.
*/
#define Tvar(d) ((d).dword & F_Tvar)
/*
* Location of trapped-variable block.
*/
#define TvarLoc(d) ((d).vword.bptr)
/*
* Type of descriptor.
*/
#define Type(d) (int)((d).dword & TypeMask)
/*
* Check for variable.
*/
#define Var(d) ((d).dword & F_Var)
/*
* Location of the value of a variable.
*/
#define VarLoc(d) ((d).vword.descptr)
/*
* Important note: The code that follows is not strictly legal C.
* It tests to see if pointer p2 is between p1 and p3. This may
* involve the comparison of pointers in different arrays, which
* is not well-defined. The casts of these pointers to unsigned "words"
* (longs or ints, depending) works with all C compilers and architectures
* on which Icon has been implemented. However, it is possible it will
* not work on some system. If it doesn't, there may be a "false
* positive" test, which is likely to cause a memory violation or a
* loop. It is not practical to implement Icon on a system on which this
* happens.
*/
#define InRange(p1,p2,p3) ((uword)(p2) >= (uword)(p1) && (uword)(p2) < (uword)(p3))
/*
* Macros for pushing values on the interpreter stack.
*/
/*
* Push descriptor.
*/
#define PushDesc(d) {*++sp = ((d).dword); sp++;*sp =((d).vword.integr);}
/*
* Push null-valued descriptor.
*/
#define PushNull {*++sp = D_Null; sp++; *sp = 0;}
/*
* Push word.
*/
#define PushVal(v) {*++sp = (word)(v);}
/*
* Macros related to function and operator definition.
*/
/*
* Procedure block for a function.
*/
#define FncBlock(f,nargs,deref) \
struct b_iproc Cat(B,f) = {\
T_Proc,\
Vsizeof(struct b_proc),\
Cat(X,f),\
nargs,\
-1,\
deref, 0,\
{sizeof(Lit(f))-1,Lit(f)}};
/*
* Function declaration for variable number of arguments.
*/
#define FncDcl(nm,n) FncBlock(nm,n,0) Cat(X,nm)(cargp) register dptr cargp;
/*
* Function declaration for variable number of arguments.
*/
#define FncDclV(nm) FncBlock(nm,-1,0) Cat(X,nm)(nargs,cargp) register dptr cargp;
/*
* Function declaration without dereferenced arguments.
*/
#define FncNDcl(nm,n) FncBlock(nm,n,-1) Cat(X,nm)(cargp) register dptr cargp;
/*
* Function declaration for variable number of arguments.
*/
#define FncNDclV(nm) FncBlock(nm,-1,-1) Cat(X,nm)(nargs,cargp) register dptr cargp;
/*
* Declaration for library routine.
*/
#define LibDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(nargs,cargp) \
register dptr cargp;
/*
* Procedure block for an operator.
*/
#define OpBlock(f,nargs,sname,realargs)\
struct b_iproc Cat(B,f) = {\
T_Proc,\
Vsizeof(struct b_proc),\
Cat(O,f),\
nargs,\
-1,\
realargs,\
0,\
{sizeof(sname)-1,sname}};
/*
* Operator declaration.
*/
#define OpDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(cargp) register dptr cargp;
/*
* Agent routine declaration.
*/
#define AgtDcl(nm) Cat(A,nm)(cargp) register dptr cargp;
#ifdef StrInvoke
/*
* Structure for mapping string names of procedures to block addresses.
*/
struct pstrnm {
char *pstrep;
struct b_proc *pblock;
};
#endif /* StrInvoke */
/*
* Macros to access Icon arguments in C functions.
*/
/*
* n-th argument.
*/
#define Arg(n) (cargp[n])
/*
* Type field of n-th argument.
*/
#define ArgType(n) (cargp[n].dword)
/*
* Value field of n-th argument.
*/
#define ArgVal(n) (cargp[n].vword.integr)
/*
* Specific arguments.
*/
#define Arg0 (cargp[0])
#define Arg1 (cargp[1])
#define Arg2 (cargp[2])
#define Arg3 (cargp[3])
#define Arg4 (cargp[4])
#define Arg5 (cargp[5])
#define Arg6 (cargp[6])
/*
* Code expansions for exits from C code for top-level routines.
*/
#define Fail return A_Failure
#define Return return A_Return
#define Suspend { \
int rc; \
if ((rc = interp(G_Csusp,cargp)) != A_Resumption) \
return rc;}
#define Forward(agent) return Cat(A,agent)(cargp)
/*
* Miscellaneous macro definitions.
*/
/*
* Error exit from non top-level routines.
*/
#define RetError(n,v) {\
k_errornumber = n;\
k_errortext = "";\
k_errorvalue = v;\
return Error;}
/*
* Get floating-point number from real block.
*/
#ifdef Double
#define GetReal(dp,res) { \
word *rp, *rq; \
rp = (word *) &(res); \
rq = (word *) &(BlkLoc(*dp)->realblk.realval); \
*rp++ = *rq++; \
*rp = *rq;}
#else /* Double */
#define GetReal(dp,res) res = BlkLoc(*dp)->realblk.realval
#endif /* Double */
/*
* Absolute value of x (word).
*/
#define Abs(x) (((x) < 0) ? (-(x)) : (x))
/*
* Maximum of x and y.
*/
#define Max(x,y) ((x)>(y)?(x):(y))
#ifdef SASC /* remove comments for Relase 4.50 */
/* #undef Max */
/* #define Max(x,y) __builtin_max(x,y) */
#endif /* SASC */
/*
* Minimum of x and y.
*/
#define Min(x,y) ((x)<(y)?(x):(y))
#ifdef SASC /* remove comments for Relase 4.50 */
/* #undef Min */
/* #define Min(x,y) __builtin_min(x,y) */
#endif /* SASC */
/*
* Some C compilers take '\n' and '\r' to be the same, so the
* following definitions are used.
*/
#if EBCDIC
/*
* Note that, in EBCDIC, "line feed" and "new line" are distinct
* characters. Icon's use of "line feed" is really "new line" in
* C terms.
*/
#define LineFeed '\n' /* if really "line feed", that's 37 */
#define CarriageReturn '\r'
#else /* EBCDIC */
#define LineFeed 10
#define CarriageReturn 13
#endif /* EBCDIC */
/*
* Construct an integer descriptor.
*/
#define MakeInt(i,dp) { \
(dp)->dword = D_Integer; \
IntVal(*dp) = (word)(i);}
/*
* Check whether a set or table needs resizing.
*/
#define SP(p) ((struct b_set *)p)
#define TooCrowded(p) \
((SP(p)->size > MaxHLoad*(SP(p)->mask+1)) && (SP(p)->hdir[HSegs-1] == NULL))
#define TooSparse(p) \
((SP(p)->hdir[1] != NULL) && (SP(p)->size < MinHLoad*(SP(p)->mask+1)))
/*
* RunErr encapsulates a call to the function runerr, followed
* by Fail. The idea is to avoid the problem of calling
* runerr directly and forgetting that it may actually return.
*/
#define RunErr(n,dp) {\
runerr((int)n,dp);\
Fail;\
}
/*
* Vsizeof is for use with variable-sized (i.e., indefinite)
* structures containing an array of descriptors declared of size 1
* to avoid compiler warnings associated with 0-sized arrays.
*/
#define Vsizeof(s) (sizeof(s) - sizeof(struct descrip))
/*
* Offset in word of cset bit.
*/
#define CsetOff(b) ((b) & BitOffMask)
/*
* Address of word of cset bit.
*/
#define CsetPtr(b,c) ((c) + (((b)&0377) >> LogIntBits))
/*
* Set bit b in cset c.
*/
#define Setb(b,c) (*CsetPtr(b,c) |= (01 << CsetOff(b)))
/*
* Test bit b in cset c.
*/
#define Testb(b,c) ((*CsetPtr(b,c) >> CsetOff(b)) & 01)
/*
* Handy sizeof macros:
*
* Wsizeof(x) -- Size of x in words.
* Vwsizeof(x) -- Size of x in words, minus the size of a descriptor. Used
* when structures have a potentially null list of descriptors
* at their end.
*/
#define Wsizeof(x) ((sizeof(x) + sizeof(word) - 1) / sizeof(word))
#define Vwsizeof(x) ((sizeof(x) - sizeof(struct descrip) +sizeof(word) - 1)\
/ sizeof(word))
/*
* Definitions and declarations used for storage management.
*/
#define F_Mark 0100000 /* bit for marking blocks */
#define Static 1 /* collection is for static region */
#define Strings 2 /* collection is for strings */
#define Blocks 3 /* collection is for blocks */
/*
* External definitions.
*/
extern char *currend; /* current end of memory region */
extern uword blkneed; /* stated need for block space */
extern uword strneed; /* stated need for string space */
extern uword statneed;
extern dptr globals; /* start of global variables */
extern dptr eglobals; /* end of global variables */
extern dptr gnames; /* start of global variable names */
extern dptr egnames; /* end of global variable names */
extern dptr statics; /* start of static variables */
extern dptr estatics; /* end of static variables */
extern dptr *quallist; /* start of qualifier list */
extern word qualsize;
/*
* Get type of block pointed at by x.
*/
#define BlkType(x) (*(word *)x)
/*
* BlkSize(x) takes the block pointed to by x and if the size of
* the block as indicated by bsizes[] is nonzero it returns the
* indicated size; otherwise it returns the second word in the
* block contains the size.
*/
#define BlkSize(x) (bsizes[*(word *)x & ~F_Mark] ? \
bsizes[*(word *)x & ~F_Mark] : *((word *)x + 1))
/*
* If memory monitoring is not enabled, redefine function calls
* to do nothing.
*/
#ifndef MemMon
#define MMAlc(n,t)
#define MMBGC(r)
#define MMEGC()
#define MMMark(b,t)
#define MMShow(d,s)
#define MMStat(a,l,c)
#define MMStr(n)
#define MMSMark(a,n)
#endif /* MemMon */
#ifndef FixedRegions
/*
* Information used with Icon's allocation routines with expandable-regions
* memory management.
*/
typedef int ALIGN; /* pick most stringent type for alignment */
union bhead { /* header of free block */
struct {
union bhead *ptr; /* pointer to next free block */
uword bsize; /* free block size */
} s;
ALIGN x; /* force block alignment */
};
typedef union bhead HEADER;
#define NALLOC 64 /* units to request at one time */
#define FREEMAGIC 0x807F /* magic flag for free blocks (MemMon only) */
#endif /* FixedRegions */